import '@assets/scss/app.scss';
import { $ } from '@utils/functions';
import { WebGL, vertex_shader, fragment_shader } from "@script/index";
import Matrix4 from '@utils/matrix4';

function render(canvas) {
  const webgl = new WebGL(canvas, _gl => {
    _gl.clearColor(0.0, 0.0, 0.0, 1.0);
    _gl.enable(_gl.DEPTH_TEST);
    _gl.depthFunc(_gl.LEQUAL);
  });
  webgl.initialize(vertex_shader, fragment_shader);
  const floatArray = [
    // 0-1-2-3
    2.0, 2.0, 2.0, -2.0, 2.0, 2.0, -2.0, -2.0, 2.0, 2.0, -2.0, 2.0,
    // 0-3-4-5
    2.0, 2.0, 2.0, 2.0, -2.0, 2.0, 2.0, -2.0, -2.0, 2.0, 2.0, -2.0,
    // 0-5-6-1
    2.0, 2.0, 2.0, 2.0, 2.0, -2.0, -2.0, 2.0, -2.0, -2.0, 2.0, 2.0,
    // 1-6-7-2
    -2.0, 2.0, 2.0, -2.0, 2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, 2.0,
    // 7-4-3-2
    -2.0, -2.0, -2.0, 2.0, -2.0, -2.0, 2.0, -2.0, 2.0, -2.0, -2.0, 2.0,
    // 4-7-6-5
    2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, 2.0, -2.0, 2.0, 2.0, -2.0
  ];

  const colorArray = [
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
  ];

  const normalArray = [
    0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
    -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
    0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,
    0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0,
  ];

  const indexArray = [
    0, 1, 2, 0, 2, 3,
    4, 5, 6, 4, 6, 7,
    8, 9, 10, 8, 10, 11,
    12, 13, 14, 12, 14, 15,
    16, 17, 18, 16, 18, 19,
    20, 21, 22, 20, 22, 23
  ];

  const { gl } = webgl;

  const a_Position = webgl.initBuffers({ attribute: 'a_Position', array: floatArray, type: gl.FLOAT, size: 3 });
  const a_Color = webgl.initBuffers({ attribute: 'a_Color', array: colorArray, type: gl.FLOAT, size: 3 });
  const a_Normal = webgl.initBuffers({ attribute: 'a_Normal', array: normalArray, type: gl.FLOAT, size: 3 });

  if (!a_Position || !a_Color || !a_Normal) return;

  webgl.buffers(indexArray, (_gl, index_array, _program) => {
    const indices = new Uint8Array(index_array);
    let n = indices.length;

    _gl.clearColor(0, 0, 0, 1);
    _gl.bufferData(_gl.ELEMENT_ARRAY_BUFFER, indices, _gl.STATIC_DRAW);

    const u_ModelMatrix = _gl.getUniformLocation(_program, 'u_ModelMatrix');
    const u_MvpMatrix = _gl.getUniformLocation(_program, 'u_MvpMatrix');
    const u_NormalMatrix = _gl.getUniformLocation(_program, 'u_NormalMatrix');
    const u_LightColor = _gl.getUniformLocation(_program, 'u_LightColor');
    const u_AmbientLight = _gl.getUniformLocation(_program, 'u_AmbientLight');
    const u_LightPosition = _gl.getUniformLocation(_program, 'u_LightPosition');

    const modelMatrix = new Matrix4();
    const normalMatrix = new Matrix4();

    modelMatrix.setRotate({ angle: 90, x: 0, y: 1, z: 0 });
    const mvpMatrix = new Matrix4().setPerspective({
      fov: 30, aspect: canvas.width / canvas.height,
      near: 1, far: 100
    }).lookAt({
      eyeX: 6, eyeY: 6, eyeZ: 14,
      centerX: 0, centerY: 0, centerZ: 0,
      upX: 0, upY: 1, upZ: 0
    }).multiply(modelMatrix);

    normalMatrix.setInverseOf(modelMatrix).transpose();

    _gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
    _gl.uniform3f(u_LightPosition, 2.3, 4.0, 3.5);
    _gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);

    _gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
    _gl.uniformMatrix4fv(u_MvpMatrix, false, mvpMatrix.elements);
    _gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);

    _gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);
    _gl.drawElements(_gl.TRIANGLES, n, _gl.UNSIGNED_BYTE, 0);
  });
}

(() => {
  const canvas = document.createElement('canvas');
  canvas.className = 'canvas';
  canvas.id = "webgl-canvas";
  canvas.width = innerWidth;
  canvas.height = innerHeight;
  $('.canvas-area').appendChild(canvas);

  render(canvas);
})();
